package com.ymm.system.core.facade;

import com.ymm.system.api.constants.CargoEntity;
import com.ymm.system.api.dto.PutOnCargoRequest;
import com.ymm.system.api.facade.SystemCargoService;
import com.ymm.system.api.utils.*;
import com.ymm.system.core.mq.sender.CargoPullOffMsgSender;
import com.ymm.system.core.mq.sender.CargoPutOnMsgSender;
import com.ymm.system.core.utils.AddressUtils;
import com.ymm.system.core.utils.FormatUtils;
import com.ymm.system.dao.mapper.CargoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;

@Slf4j
@Service
public class SystemCargoServiceImpl implements SystemCargoService {

    @Resource
    private CargoMapper cargoMapper;

    @Resource
    private CargoPullOffMsgSender cargoPullOffMsgSender;

    private static final int CARGO_DESCRIPTION_MAX_LENGTH = 50;
    private static final Integer MAX_PERSON_NUM = 3;
    private static final int CARGO_COMMENT_MAX_LENGTH = 50;

    /**
     * 发货
     *
     * @param putOnCargoRequest 发货request
     * @param opsPersonType     操作人类型，可以为空
     * @param opsPersonId       操作人Id，可以为空
     * @return 是否成功
     */
    @Override
    public Result<Long> cargoDeliver(PutOnCargoRequest putOnCargoRequest, Integer opsPersonType, Long opsPersonId) {
        Result<Boolean> putOnCargoRequestParametersCheckResult = putOnCargoRequestParametersCheck(putOnCargoRequest);
        if (putOnCargoRequestParametersCheckResult == null) {
            return Result.fail(null, ResultCodeEnum.PARAM_ERROR);
        }
        if (!putOnCargoRequestParametersCheckResult.isSuccess()) {
            return Result.fail(null, putOnCargoRequestParametersCheckResult.getCode(), putOnCargoRequestParametersCheckResult.getMessage());
        }
        //1.封装cargo
        CargoEntity cargo = new CargoEntity();
        BeanUtils.copyProperties(putOnCargoRequest, cargo);
        cargo.setCargoDesLon(putOnCargoRequest.getCargoDesLon().doubleValue());
        cargo.setCargoDesLat(putOnCargoRequest.getCargoDesLat().doubleValue());
        cargo.setCargoSrcLat(putOnCargoRequest.getCargoSrcLat().doubleValue());
        cargo.setCargoSrcLon(putOnCargoRequest.getCargoSrcLon().doubleValue());
        double cargoDistance = SystemMatchServiceImpl.algorithm(putOnCargoRequest.getCargoDesLon().doubleValue(),
                putOnCargoRequest.getCargoDesLat().doubleValue(),
                putOnCargoRequest.getCargoSrcLon().doubleValue(),
                putOnCargoRequest.getCargoSrcLat().doubleValue());
        cargo.setCargoDistance((int) cargoDistance);
        cargo.setCargoCreateTime(new Date());
        cargo.setCargoUpdateTime(new Date());
//        cargo.setCargoState(CargoStatusEnum.ON_SHLFE.getCode());
        cargo.setCargoState(CargoStatusEnum.WAIT_FOR_PAY.getCode());
        //2.写入数据库
        cargoMapper.deliverCargoByShipper(cargo);

        return Result.success(cargo.getCargoId());
    }

    /**
     * 下架在上架的货源
     *
     * @param cargoId       货源Id
     * @param opsPersonType 操作人类型，可以为空
     * @param opsPersonId   操作人Id，可以为空
     * @return 是否成功
     */
    @Override
    @Transactional
    public Result<Long> cancelOnShelfCargo(Long cargoId, Integer opsPersonType, Long opsPersonId) throws Exception{
        //1.查询货源状态信息
        CargoEntity cargo = cargoMapper.queryCargoByCargoId(cargoId);

        // 检测是否包含该货源
        if (null == cargo) {
            return Result.fail(null, ResultCodeEnum.PARAM_ERROR.getCode(), "无此货源！");
        }

        //3.下架货源
        Integer state = cargoMapper.updateCargoStateFromTo(cargoId, CargoStatusEnum.ON_SHLFE.getCode(), CargoStatusEnum.OFF_SHLFE.getCode());
        if (state == 0) {
            Integer cargoState = cargoMapper.queryCargoStateById(cargoId);
            if (cargoState.equals(CargoStatusEnum.OFF_SHLFE.getCode())) {
                log.error("取消失败，货源已下架：cargoState={}", cargoState);
                return Result.fail(null, ResultCodeEnum.FAIL.getCode(), "失败！货源已下架");
            } else if (cargoState.equals(CargoStatusEnum.HOLDING.getCode())) {
                log.error("取消失败，货源已接单：cargoState={}", cargoState);
                return Result.fail(null, ResultCodeEnum.FAIL.getCode(), "失败！货源已接单");
            }
        }

        //给货主发送消息
        try {
            cargoPullOffMsgSender.send(cargoId, cargo.getShipperId(), null, opsPersonType, opsPersonId, cargo.getCargoPrice());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消息发送错误");
            throw new RuntimeException(e);
        }
        return Result.success(cargoId);
    }

    /**
     * 下架被接单的货源
     *
     * @param cargoId       货源Id
     * @param opsPersonType 操作人类型，可以为空
     * @param opsPersonId   操作人Id，可以为空
     * @return 是否成功
     */
    @Override
    @Transactional
    public Result<Long> cancelHodingCargo(Long cargoId, Long orderId, Integer opsPersonType, Long opsPersonId) throws Exception{
        //1.查询货源状态信息
        CargoEntity cargo = cargoMapper.queryCargoByCargoId(cargoId);


        // 检测是否包含该货源
        if (null == cargo) {
            return Result.fail(null, ResultCodeEnum.PARAM_ERROR.getCode(), "无此货源！");
        }

        //3.下架货源
        Integer state = cargoMapper.updateCargoStateFromTo(cargoId, CargoStatusEnum.HOLDING.getCode(), CargoStatusEnum.OFF_SHLFE.getCode());
        if (state == 0) {
            Integer cargoState = cargoMapper.queryCargoStateById(cargoId);
            if (cargoState.equals(CargoStatusEnum.OFF_SHLFE.getCode())) {
                log.error("取消失败，货源已下架：cargoState={}", cargoState);
                return Result.fail(null, ResultCodeEnum.FAIL.getCode(), "失败！货源已下架");
            } else if (cargoState.equals(CargoStatusEnum.ON_SHLFE.getCode())) {
                log.error("取消失败，货源上架中：cargoState={}", cargoState);
                return Result.fail(null, ResultCodeEnum.FAIL.getCode(), "失败！货源已接单");
            }
        }

        //给货主发送消息
        try {
            cargoPullOffMsgSender.send(cargoId, cargo.getShipperId(), orderId, opsPersonType, opsPersonId, cargo.getCargoPrice());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消息发送错误");
            throw new RuntimeException(e);
        }
        return Result.success(cargoId);
    }

    /**
     * 发货请求参数校验
     *
     * @param putOnCargoRequest 发货请求
     * @return 结果
     */
    private Result<Boolean> putOnCargoRequestParametersCheck(PutOnCargoRequest putOnCargoRequest) {
        if (putOnCargoRequest == null || putOnCargoRequest.getShipperId() == null || putOnCargoRequest.getCargoDeliveryTime() == null || Objects.isNull(putOnCargoRequest.getCargoType())) {
            return Result.fail(null, ResultCodeEnum.PARAM_ERROR);
        }
        if (!AddressUtils.latLongCheck(putOnCargoRequest.getCargoSrcLat(), putOnCargoRequest.getCargoSrcLon())) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "装货地位置错误！");
        }
        if (!AddressUtils.latLongCheck(putOnCargoRequest.getCargoDesLat(), putOnCargoRequest.getCargoDesLon())) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "卸货地位置错误！");
        }
        if (putOnCargoRequest.getCargoSrc() == null || putOnCargoRequest.getCargoSrc().length() == 0 || !AddressUtils.provCityRegionCheck(putOnCargoRequest.getCargoSrcProv(), putOnCargoRequest.getCargoSrcCity(), putOnCargoRequest.getCargoSrcRegion())) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "装货地位置错误");
        }
        if (putOnCargoRequest.getCargoDes() == null || putOnCargoRequest.getCargoDes().length() == 0 || !AddressUtils.provCityRegionCheck(putOnCargoRequest.getCargoDesProv(), putOnCargoRequest.getCargoDesCity(), putOnCargoRequest.getCargoDesRegion())) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "卸货地位置错误");
        }
        if (!cargoRequireTypeCheck(putOnCargoRequest.getCargoRequireType())) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "所需车类型参数错误！");
        }
        if (putOnCargoRequest.getCargoDescription() == null || putOnCargoRequest.getCargoDescription().length() == 0) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "货物描述不能为空!");
        }
        if (putOnCargoRequest.getCargoDescription().length() > CARGO_DESCRIPTION_MAX_LENGTH) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "货物描述字数过长！");
        }
        if (putOnCargoRequest.getCargoPrice() == null || putOnCargoRequest.getCargoPrice().compareTo(0) < 0) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "货物定价错误");
        }
        if (putOnCargoRequest.getCargoPersonNum() == null || putOnCargoRequest.getCargoPersonNum().compareTo(0) < 0) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "跟车人数错误");
        }
        if (putOnCargoRequest.getCargoPersonNum() > MAX_PERSON_NUM) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "跟车人数超过最大值");
        }
        if (putOnCargoRequest.getCargoComment() != null && putOnCargoRequest.getCargoComment().length() > CARGO_COMMENT_MAX_LENGTH) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "备注字数超过最大值");
        }
        if (Objects.nonNull(putOnCargoRequest.getCargoShipperPhone()) && !FormatUtils.checkPhoneNumberFormat(putOnCargoRequest.getCargoShipperPhone())) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "发货人联系方式格式错误");
        }
        if (Objects.nonNull(putOnCargoRequest.getCargoReceiverPhone()) && !FormatUtils.checkPhoneNumberFormat(putOnCargoRequest.getCargoReceiverPhone())) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "收货人联系方式格式错误");
        }
        if (Objects.nonNull(putOnCargoRequest.getCargoVolume()) && putOnCargoRequest.getCargoVolume().compareTo(BigDecimal.ZERO) <0) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "体积不可为负数");
        }
        if (Objects.nonNull(putOnCargoRequest.getCargoWeight()) && putOnCargoRequest.getCargoWeight().compareTo(BigDecimal.ZERO) <0) {
            return Result.fail(null, com.ymm.lulutong.constant.ResultCodeEnum.PARAM_ERROR.getCode(), "重量不可为负数");
        }
        return Result.success();
    }

    /**
     * 所需车辆类型校验
     *
     * @param cargoRequireType 所需车辆类型（Integer）
     * @return 结果
     */
    private boolean cargoRequireTypeCheck(Integer cargoRequireType) {
        return cargoRequireType >= 1 && cargoRequireType <= 9;
    }
}
